home *** CD-ROM | disk | FTP | other *** search
/ Programming a Multiplayer FPS in DirectX / Programming a Multiplayer FPS in DirectX (Companion CD).iso / Source / Chapter 12 / Game / Game.cpp next >
Encoding:
C/C++ Source or Header  |  2004-10-01  |  9.8 KB  |  301 lines

  1. //-----------------------------------------------------------------------------
  2. // Game.h implementation.
  3. // Refer to the Game.h interface for more details.
  4. //
  5. // Programming a Multiplayer First Person Shooter in DirectX
  6. // Copyright (c) 2004 Vaughan Young
  7. //-----------------------------------------------------------------------------
  8. #include "Main.h"
  9.  
  10. //-----------------------------------------------------------------------------
  11. // Globals
  12. //-----------------------------------------------------------------------------
  13. Game *g_game = NULL;
  14.  
  15. //-----------------------------------------------------------------------------
  16. // Game class constructor.
  17. //-----------------------------------------------------------------------------
  18. Game::Game() : State( STATE_GAME )
  19. {
  20.     // Store a pointer to the game state in a global variable for easy access.
  21.     g_game = this;
  22.  
  23.     // Invalidate the score board font.
  24.     m_scoreBoardFont = NULL;
  25.  
  26.     // Invalidate the player manager.
  27.     m_playerManager = NULL;
  28. }
  29.  
  30. //-----------------------------------------------------------------------------
  31. // Allows the game state to preform any pre-processing construction.
  32. //-----------------------------------------------------------------------------
  33. void Game::Load()
  34. {
  35.     // Hide the mouse cursor.
  36.     ShowCursor( false );
  37.  
  38.     // Load the crosshair material.
  39.     m_crosshair = g_engine->GetMaterialManager()->Add( "Crosshair.dds.txt", "./Assets/" );
  40.  
  41.     // Create the score board font.
  42.     m_scoreBoardFont = new Font( "Arial", 14, FW_BOLD );
  43.     m_scoreBoardNames[0] = 0;
  44.     m_scoreBoardFrags[0] = 0;
  45.     m_scoreBoardDeaths[0] = 0;
  46.  
  47.     // Create both the player manager.
  48.     m_playerManager = new PlayerManager;
  49. }
  50.  
  51. //-----------------------------------------------------------------------------
  52. // Allows the game state to preform any post-processing destruction.
  53. //-----------------------------------------------------------------------------
  54. void Game::Close()
  55. {
  56.     // Show the mouse cursor.
  57.     ShowCursor( true );
  58.  
  59.     // Terminate the session.
  60.     g_engine->GetNetwork()->Terminate();
  61.  
  62.     // Destroy the scene.
  63.     g_engine->GetSceneManager()->DestroyScene();
  64.  
  65.     // Destroy both the player manager.
  66.     SAFE_DELETE( m_playerManager );
  67.  
  68.     // Destroy the score board font.
  69.     SAFE_DELETE( m_scoreBoardFont );
  70.  
  71.     // Destroy the crosshair material.
  72.     g_engine->GetMaterialManager()->Remove( &m_crosshair );
  73. }
  74.  
  75. //-----------------------------------------------------------------------------
  76. // Returns the view setup details for the given frame.
  77. //-----------------------------------------------------------------------------
  78. void Game::RequestViewer( ViewerSetup *viewer )
  79. {
  80.     viewer->viewer = m_playerManager->GetViewingPlayer();
  81.     viewer->viewClearFlags = D3DCLEAR_ZBUFFER;
  82. }
  83.  
  84. //-----------------------------------------------------------------------------
  85. // Update the game state.
  86. //-----------------------------------------------------------------------------
  87. void Game::Update( float elapsed )
  88. {
  89.     // Allow the player to respawn by pressing the R key.
  90.     if( g_engine->GetInput()->GetKeyPress( DIK_R ) == true )
  91.     {
  92.         m_playerManager->GetLocalPlayer()->SetEnabled( false );
  93.         m_playerManager->SpawnLocalPlayer();
  94.     }
  95.  
  96.     // Update the player manager.
  97.     m_playerManager->Update( elapsed );
  98.  
  99.     // Check if the user is holding down the tab key.
  100.     if( g_engine->GetInput()->GetKeyPress( DIK_TAB, true ) == true )
  101.     {
  102.         // Build the score board text.
  103.         sprintf( m_scoreBoardNames, "PLAYER\n" );
  104.         sprintf( m_scoreBoardFrags, "FRAGS\n" );
  105.         sprintf( m_scoreBoardDeaths, "DEATHS\n" );
  106.  
  107.         // Add each player's details to the score board.
  108.         PlayerObject *player = m_playerManager->GetNextPlayer( true );
  109.         while( player != NULL )
  110.         {
  111.             strcat( m_scoreBoardNames, player->GetName() );
  112.             strcat( m_scoreBoardNames, "\n" );
  113.  
  114.             sprintf( m_scoreBoardFrags, "%s%d", m_scoreBoardFrags, player->GetFrags() );
  115.             strcat( m_scoreBoardFrags, "\n" );
  116.  
  117.             sprintf( m_scoreBoardDeaths, "%s%d", m_scoreBoardDeaths, player->GetDeaths() );
  118.             strcat( m_scoreBoardDeaths, "\n" );
  119.  
  120.             player = m_playerManager->GetNextPlayer();
  121.         }
  122.     }
  123.  
  124.     // Check if the user wants to exit back to the menu.
  125.     if( g_engine->GetInput()->GetKeyPress( DIK_ESCAPE ) )
  126.         g_engine->ChangeState( STATE_MENU );
  127. }
  128.  
  129. //-----------------------------------------------------------------------------
  130. // Render the game state.
  131. //-----------------------------------------------------------------------------
  132. void Game::Render()
  133. {
  134.     // Ensure the scene is loaded.
  135.     if( g_engine->GetSceneManager()->IsLoaded() == false )
  136.         return;
  137.  
  138.     // If the user is holding down the tab key, then render the score board.
  139.     if( g_engine->GetInput()->GetKeyPress( DIK_TAB, true ) == true )
  140.     {
  141.         m_scoreBoardFont->Render( m_scoreBoardNames, 20, 100, 0xFFFF7700 );
  142.         m_scoreBoardFont->Render( m_scoreBoardFrags, 180, 100, 0xFFFF7700 );
  143.         m_scoreBoardFont->Render( m_scoreBoardDeaths, 260, 100, 0xFFFF7700 );
  144.     }
  145.  
  146.     // Draw the local player's crosshair in the centre of the screen.
  147.     g_engine->GetSprite()->Begin( D3DXSPRITE_ALPHABLEND );
  148.     g_engine->GetSprite()->Draw( m_crosshair->GetTexture(), NULL, NULL, &D3DXVECTOR3( g_engine->GetDisplayMode()->Width / 2.0f - 15.0f, g_engine->GetDisplayMode()->Height / 2.0f - 15.0f, 0.0f ), 0xFFFFFFFF );
  149.     g_engine->GetSprite()->End();
  150. }
  151.  
  152. //-----------------------------------------------------------------------------
  153. // Handles the game specific network messages. Called by the network object.
  154. //-----------------------------------------------------------------------------
  155. void Game::HandleNetworkMessage( ReceivedMessage *msg )
  156. {
  157.     // Process the received messaged based on its type.
  158.     switch( msg->msgid )
  159.     {
  160.         case MSGID_CREATE_PLAYER:
  161.         {
  162.             // Add the new player to the player manager and the scene.
  163.             PlayerObject *object = m_playerManager->AddPlayer( g_engine->GetNetwork()->GetPlayer( msg->dpnid ) );
  164.             g_engine->GetSceneManager()->AddObject( object );
  165.  
  166.             // Check if the new player is the host player.
  167.             if( object->GetID() == g_engine->GetNetwork()->GetHostID() )
  168.             {
  169.                 // Load the scene from the host player's selection.
  170.                 g_engine->GetSceneManager()->LoadScene( ( (PlayerData*)g_engine->GetNetwork()->GetPlayer( msg->dpnid )->data )->map, "./Assets/Scenes/" );
  171.  
  172.                 // Allow the network to receive game specific messages.
  173.                 g_engine->GetNetwork()->SetReceiveAllowed( true );
  174.             }
  175.  
  176.             break;
  177.         }
  178.  
  179.         case MSGID_DESTROY_PLAYER:
  180.         {
  181.             // Remove the player from the player manager and the scene.
  182.             SceneObject *object = m_playerManager->GetPlayer( msg->dpnid );
  183.             g_engine->GetSceneManager()->RemoveObject( &object );
  184.             m_playerManager->RemovePlayer( msg->dpnid );
  185.  
  186.             break;
  187.         }
  188.  
  189.         case MSGID_PLAYER_HEALTH:
  190.         {
  191.             // Get a pointer to the game specific network message.
  192.             PlayerHealthMsg *phm = (PlayerHealthMsg*)msg;
  193.  
  194.             // Set the player's health.
  195.             m_playerManager->GetPlayer( phm->dpnid )->SetHealth( phm->health );
  196.  
  197.             // Check if the player has been killed.
  198.             if( phm->health <= 0.0f )
  199.                 m_playerManager->GetPlayer( phm->dpnid )->Kill();
  200.  
  201.             break;
  202.         }
  203.  
  204.         case MSGID_PLAYER_MOVE_UPDATE:
  205.         {
  206.             // Get a pointer to the game specific network message.
  207.             PlayerMoveUpdateMsg *pmum = (PlayerMoveUpdateMsg*)msg;
  208.  
  209.             // Get a pointer to the player in question.
  210.             PlayerObject *player = m_playerManager->GetPlayer( pmum->dpnid );
  211.  
  212.             // If the player is disabled then chances are the local player has
  213.             // just joined the game, and is receiving messages about a player
  214.             // that it does not realise has already spawned. So just enable
  215.             // that player and start updating it.
  216.             if( player->GetEnabled() == false )
  217.             {
  218.                 player->SetEnabled( true );
  219.                 player->SetVisible( true );
  220.             }
  221.  
  222.             // Update all the player's details.
  223.             player->SetTranslation( pmum->translation.x, pmum->translation.y, pmum->translation.z );
  224.             player->SetDrive( pmum->drive );
  225.             player->SetStrafe( pmum->strafe );
  226.             player->SetFire( pmum->fire );
  227.  
  228.             break;
  229.         }
  230.  
  231.         case MSGID_PLAYER_LOOK_UPDATE:
  232.         {
  233.             // Get a pointer to the game specific network message.
  234.             PlayerLookUpdateMsg *plum = (PlayerLookUpdateMsg*)msg;
  235.  
  236.             // Update the player's rotation and view tilt.
  237.             m_playerManager->GetPlayer( plum->dpnid )->SetRotation( 0.0f, plum->rotationY, 0.0f );
  238.             m_playerManager->GetPlayer( plum->dpnid )->SetViewTilt( plum->viewTilt );
  239.  
  240.             break;
  241.         }
  242.  
  243.         case MSGID_PLAYER_SCORE:
  244.         {
  245.             // Get a pointer to the game specific network message.
  246.             PlayerScoreMsg *psm = (PlayerScoreMsg*)msg;
  247.  
  248.             // Update the player's score.
  249.             m_playerManager->GetPlayer( psm->dpnid )->SetFrags( psm->frags );
  250.             m_playerManager->GetPlayer( psm->dpnid )->SetDeaths( psm->deaths );
  251.  
  252.             break;
  253.         }
  254.  
  255.         case MSGID_SPAWN_POINT_REQUEST:
  256.         {
  257.             // Send a spawn point message back to the requesting player.
  258.             SpawnPointMsg spm;
  259.             spm.msgid = MSGID_SPAWN_POINT;
  260.             spm.dpnid = msg->dpnid;
  261.             spm.spawnPoint = g_engine->GetSceneManager()->GetSpawnPointID( g_engine->GetSceneManager()->GetRandomPlayerSpawnPoint() );
  262.             g_engine->GetNetwork()->Send( &spm, sizeof( SpawnPointMsg ), msg->dpnid );
  263.  
  264.             break;
  265.         }
  266.  
  267.         case MSGID_SPAWN_POINT:
  268.         {
  269.             // Get a pointer to the game specific network message.
  270.             SpawnPointMsg *spm = (SpawnPointMsg*)msg;
  271.  
  272.             // Ensure this message is for the local player.
  273.             if( spm->dpnid != g_engine->GetNetwork()->GetLocalID() )
  274.                 break;
  275.  
  276.             // Spawn the local player using this spawn point.
  277.             m_playerManager->SpawnLocalPlayer( spm->spawnPoint );
  278.  
  279.             break;
  280.         }
  281.  
  282.         case MSGID_SPAWN_PLAYER:
  283.         {
  284.             // Get a pointer to the game specific network message.
  285.             SpawnPlayerMsg *spm = (SpawnPlayerMsg*)msg;
  286.  
  287.             // Spawn the player.
  288.             m_playerManager->SpawnPlayer( spm->dpnid, spm->translation );
  289.  
  290.             break;
  291.         }
  292.  
  293.         case MSGID_TERMINATE_SESSION:
  294.         {
  295.             // Switch to the menu state.
  296.             g_engine->ChangeState( STATE_MENU );
  297.  
  298.             break;
  299.         }
  300.     }
  301. }